#ifndef INC_TRAP_H
#define INC_TRAP_H

#include <stdint.h>

typedef uint64_t i128[2];

struct trapframe {
    /**
     * to make musl happy
     */
    uint64_t unused;
    uint64_t tpidr;
    i128 q0;

    /**
     * stack pointers are stored in SP_ELx, which is
     * maintained by the architecture.
     * PSTATE & PC are stored in SPSR_EL1 & ELR_EL1
     * respectively, and they will be restored when
     * `eret` is invoked.
     *
     * in order to facilitate scheduling, we can store
     * them in the trap frame.
     *
     * note that kernel interrupts are disabled. Therefore,
     * SP, PSTATE and PC are required to be saved only when
     * scheduling begins. We may delay saving these registers
     * until context switch.
     */
    uint64_t pstate;
    uint64_t pc;
    uint64_t stack;

    /**
     * general-purpose registers x0-x30.
     *
     * since general-purpose registers must be saved first,
     * they have to be the last part of trap frame.
     */
    uint64_t x[31];

    /**
     * for now, we do not care about floating-pointing
     * registers.
     */
};

void trap(struct trapframe *);
void irq_init();
void irq_error();
void report_and_exit();

#endif
